﻿using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
using Project.Core.Config.Config.Cache;
using Project.Core.Config.Config.Jwt;
using System.Diagnostics;

namespace Project.Core.Config.Common.Filter {
    public class AuthorizeFilter : IAuthorizationFilter {

        private readonly ILogger _logger;
        private readonly ICacheHelper _cache;
        private readonly IConfiguration _configuration;
        //private readonly UserService userService;

        public AuthorizeFilter(ICacheHelper cache, ILogger<AuthorizeFilter> logger, IConfiguration configuration) {
            this._logger = logger;
            this._cache = cache;
            this._configuration = configuration;
            //this.userService = userService;
        }

        public void OnAuthorization(AuthorizationFilterContext context) {
            _logger.LogInformation("登录认证过滤器");

            //如果controller或方法上有Authorize,且token过期或没带token的请求,会进入这里判断
            if (context.HttpContext.Request.Path.Value == "/Error/401") {
                Debug.WriteLine("/Error/401");
                UpdateToken(context);
            }

            var actionDescriptor = context.ActionDescriptor;
            if (actionDescriptor.EndpointMetadata.Any(p => p is AllowAnonymousAttribute)) {
                _logger.LogInformation("跳过过滤器");
                return;
            } else {
                //判断是否登录
                if (context.HttpContext.User.Identity.IsAuthenticated) {
                    _logger.LogInformation("检查令牌是否可用");

                    //判断该token是否已经登出
                    List<string> authorizations = new List<string>();
                    if (_cache.IsExist(context.HttpContext.User.Identity.Name)) {
                        authorizations = _cache.Get<List<string>>(context.HttpContext.User.Identity.Name);
                        //Debug.WriteLine(JsonConvert.SerializeObject(authorizations));
                        if (authorizations.Contains(context.HttpContext.Request.Headers["Authorization"])) {
                            context.Result = new JsonResult(new { code = StatusCodes.Status401Unauthorized, msg = "请先登录" });
                        }
                    }
                }
                //如果controller或方法上没有Authorize, 且token过期或没带token的请求都不会出现401状态码, 也获取不了name, 并执行下面代码

            }
        }

        private void UpdateToken(AuthorizationFilterContext context) {
            //判断缓存中的tokan是否过期
            if (_cache.IsExist(context.HttpContext.Request.Headers["Authorization"])) {
                _logger.LogInformation("还没过期，更新Token");
                string username = _cache.Get<string>(context.HttpContext.Request.Headers["Authorization"]);
                if (username == "正在更新token") {
                    context.Result = new JsonResult(new { code = StatusCodes.Status401Unauthorized, msg = "正在更新Token" });
                    return;
                }
                //保留旧的token30秒，在这30秒用旧的token来的请求都是返回“正在更新token”
                _cache.Set(context.HttpContext.Request.Headers["Authorization"], "正在更新token", 30);
                var jwtConfig = _configuration.GetSection("JwtConfig").Get<JwtConfigInfo>();
                //把旧的token放进登出名单
                List<string> authorizations = new List<string>();
                if (_cache.IsExist(username)) {
                    authorizations = _cache.Get<List<string>>(username);
                }
                authorizations.Add(context.HttpContext.Request.Headers["Authorization"]);
                _cache.Set(username, authorizations, jwtConfig.Expires);
                //没有过期则重新获取token，重新计时
                //var user = userService.login(username);
                //if (user != null) {
                //    string token = JwtToken.getToken(jwtConfig, username, user.authorities);
                //    //把token存进缓存，过期时间为token的4倍
                //    token = "Bearer " + token;
                //    cache.Set(token, username, jwtConfig.expires * 4);
                //    context.Result = new JsonResult(new { code = StatusCodes.Status401Unauthorized, msg = "更新Token", data = token });
                //    return;
                //} else {
                //    context.Result = new JsonResult(new { code = StatusCodes.Status401Unauthorized, msg = "请先登录" });
                //}
            } else {
                context.Result = new JsonResult(new { code = StatusCodes.Status401Unauthorized, msg = "请先登录" });
            }
        }

    }
}
